{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6e75c37b",
   "metadata": {},
   "source": [
    "经营现金流/净利润 > 1 → 非常健康；0.7 ~ 1 → 基本健康；< 0.7 → 需要警惕\n",
    "出现这个比值远小于1的原因有\n",
    "1、还债\n",
    "2、应收账款过多"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5acdde95",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\liangcheng\\AppData\\Local\\Temp\\ipykernel_21464\\1958678966.py:67: FutureWarning: DataFrame.applymap has been deprecated. Use DataFrame.map instead.\n",
      "  profit_annual[['净利润', '扣非净利润']] = profit_annual[['净利润', '扣非净利润']].replace('--', None).applymap(parse_amount)\n",
      "C:\\Users\\liangcheng\\AppData\\Local\\Temp\\ipykernel_21464\\1958678966.py:98: FutureWarning: DataFrame.applymap has been deprecated. Use DataFrame.map instead.\n",
      "  profit_quarter[['净利润', '扣非净利润']] = profit_quarter[['净利润', '扣非净利润']].replace('--', None).applymap(parse_amount)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== 最近3年静态数据（按年度） ===\n",
      "       报告期      净利润    扣非净利润 经营活动产生的现金流量净额   健康度 经营现金流/净利润 经营现金流/净利润健康度  \\\n",
      "0  2024.00  445.08亿  448.38亿       633.36亿  非常健康      1.42         非常健康   \n",
      "1  2023.00  464.55亿  464.31亿       924.61亿  非常健康      1.99         非常健康   \n",
      "2  2022.00  455.16亿  454.07亿      1345.72亿  非常健康      2.96         非常健康   \n",
      "3  2021.00  363.36亿  362.30亿     -1927.33亿  需要警惕     -5.30         需要警惕   \n",
      "\n",
      "  经营现金流/扣非净利润 经营现金流/扣非净利润健康度  \n",
      "0        1.41           非常健康  \n",
      "1        1.99           非常健康  \n",
      "2        2.96           非常健康  \n",
      "3       -5.32           需要警惕  \n",
      "\n",
      "=== 最近3年静态数据合计 ===\n",
      "      报告期       净利润     扣非净利润 经营活动产生的现金流量净额 健康度 经营现金流/净利润 经营现金流/扣非净利润  \\\n",
      "0  最近3年合计  1728.15亿  1729.06亿       976.36亿  一般      0.56        0.56   \n",
      "\n",
      "  经营现金流/净利润健康度 经营现金流/扣非净利润健康度  \n",
      "0           一般             一般  \n",
      "\n",
      "=== 最近12季度TTM合计 ===\n",
      "           报告期       净利润     扣非净利润 经营活动产生的现金流量净额   健康度 经营现金流/净利润 经营现金流/扣非净利润  \\\n",
      "0  最近12季度TTM合计  1377.25亿  1378.46亿      3061.88亿  非常健康      2.22        2.22   \n",
      "\n",
      "  经营现金流/净利润健康度 经营现金流/扣非净利润健康度  \n",
      "0         非常健康           非常健康  \n",
      "\n",
      "说明：经营现金流/净利润 > 1 → 非常健康；0.7 ~ 1 → 基本健康；< 0.5 → 需要警惕\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\liangcheng\\AppData\\Local\\Temp\\ipykernel_21464\\1958678966.py:132: FutureWarning: DataFrame.applymap has been deprecated. Use DataFrame.map instead.\n",
      "  '经营现金流/扣非净利润', '经营现金流/扣非净利润健康度']].applymap(lambda x: format_number(x) if isinstance(x, (int, float)) else x))\n",
      "C:\\Users\\liangcheng\\AppData\\Local\\Temp\\ipykernel_21464\\1958678966.py:135: FutureWarning: DataFrame.applymap has been deprecated. Use DataFrame.map instead.\n",
      "  print(pd.DataFrame([static_sum]).applymap(lambda x: format_number(x) if isinstance(x, (int, float)) else x))\n",
      "C:\\Users\\liangcheng\\AppData\\Local\\Temp\\ipykernel_21464\\1958678966.py:138: FutureWarning: DataFrame.applymap has been deprecated. Use DataFrame.map instead.\n",
      "  print(pd.DataFrame([ttm_sum]).applymap(lambda x: format_number(x) if isinstance(x, (int, float)) else x))\n"
     ]
    }
   ],
   "source": [
    "import akshare as ak\n",
    "import pandas as pd\n",
    "\n",
    "stock_code = \"000001\"\n",
    "\n",
    "recent_year_count = 3\n",
    "\n",
    "def parse_amount(x):\n",
    "    if pd.isna(x):\n",
    "        return None\n",
    "    if isinstance(x, (int, float)):\n",
    "        return x\n",
    "    x = str(x).replace(\",\", \"\").strip()\n",
    "    sign = -1 if x.startswith(\"-\") else 1\n",
    "    x = x.lstrip(\"+-\")\n",
    "    if \"亿\" in x:\n",
    "        return sign * float(x.replace(\"亿\", \"\")) * 1e8\n",
    "    elif \"万\" in x:\n",
    "        return sign * float(x.replace(\"万\", \"\")) * 1e4\n",
    "    elif x == \"\":\n",
    "        return None\n",
    "    else:\n",
    "        try:\n",
    "            return sign * float(x)\n",
    "        except:\n",
    "            return None\n",
    "\n",
    "def format_number(val):\n",
    "    if val is None:\n",
    "        return \"\"\n",
    "    abs_val = abs(val)\n",
    "    if abs_val >= 1e8:\n",
    "        return f\"{val / 1e8:.2f}亿\"\n",
    "    elif abs_val >= 1e4:\n",
    "        return f\"{val / 1e4:.2f}万\"\n",
    "    else:\n",
    "        return f\"{val:.2f}\"\n",
    "\n",
    "def health_level(cashflow, net_profit):\n",
    "    if net_profit is None or net_profit == 0 or cashflow is None:\n",
    "        return \"无数据\"\n",
    "    ratio = cashflow / net_profit\n",
    "    if ratio > 1:\n",
    "        return \"非常健康\"\n",
    "    elif 0.7 <= ratio <= 1:\n",
    "        return \"基本健康\"\n",
    "    elif ratio < 0.5:\n",
    "        return \"需要警惕\"\n",
    "    else:\n",
    "        return \"一般\"\n",
    "\n",
    "def ratio_health_desc(ratio):\n",
    "    if ratio is None:\n",
    "        return \"无数据\"\n",
    "    if ratio > 1:\n",
    "        return \"非常健康\"\n",
    "    elif 0.7 <= ratio <= 1:\n",
    "        return \"基本健康\"\n",
    "    elif ratio < 0.5:\n",
    "        return \"需要警惕\"\n",
    "    else:\n",
    "        return \"一般\"\n",
    "\n",
    "# 年度静态数据，取最近3年\n",
    "profit_annual = ak.stock_financial_abstract_ths(symbol=stock_code, indicator=\"按年度\")\n",
    "profit_annual = profit_annual[['报告期', '净利润', '扣非净利润']].copy()\n",
    "profit_annual[['净利润', '扣非净利润']] = profit_annual[['净利润', '扣非净利润']].replace('--', None).applymap(parse_amount)\n",
    "profit_annual = profit_annual.sort_values(\"报告期\", ascending=False).head(recent_year_count).reset_index(drop=True)\n",
    "\n",
    "cashflow_annual = ak.stock_financial_cash_ths(symbol=stock_code, indicator=\"按年度\")\n",
    "cashflow_annual = cashflow_annual[['报告期', '经营活动产生的现金流量净额']].copy()\n",
    "cashflow_annual['经营活动产生的现金流量净额'] = cashflow_annual['经营活动产生的现金流量净额'].replace('--', None).apply(parse_amount)\n",
    "cashflow_annual = cashflow_annual.sort_values(\"报告期\", ascending=False).head(recent_year_count).reset_index(drop=True)\n",
    "\n",
    "df_annual = pd.merge(profit_annual, cashflow_annual, on=\"报告期\")\n",
    "df_annual['健康度'] = df_annual.apply(lambda row: health_level(row['经营活动产生的现金流量净额'], row['净利润']), axis=1)\n",
    "df_annual['经营现金流/净利润'] = df_annual.apply(lambda row: row['经营活动产生的现金流量净额']/row['净利润'] if row['净利润'] else None, axis=1)\n",
    "df_annual['经营现金流/扣非净利润'] = df_annual.apply(lambda row: row['经营活动产生的现金流量净额']/row['扣非净利润'] if row['扣非净利润'] else None, axis=1)\n",
    "df_annual['经营现金流/净利润健康度'] = df_annual['经营现金流/净利润'].apply(ratio_health_desc)\n",
    "df_annual['经营现金流/扣非净利润健康度'] = df_annual['经营现金流/扣非净利润'].apply(ratio_health_desc)\n",
    "\n",
    "# 最近3年静态合计\n",
    "static_sum = {\n",
    "    '报告期': '最近3年合计',\n",
    "    '净利润': df_annual['净利润'].sum(),\n",
    "    '扣非净利润': df_annual['扣非净利润'].sum(),\n",
    "    '经营活动产生的现金流量净额': df_annual['经营活动产生的现金流量净额'].sum(),\n",
    "}\n",
    "static_sum['健康度'] = health_level(static_sum['经营活动产生的现金流量净额'], static_sum['净利润'])\n",
    "static_sum['经营现金流/净利润'] = static_sum['经营活动产生的现金流量净额']/static_sum['净利润'] if static_sum['净利润'] else None\n",
    "static_sum['经营现金流/扣非净利润'] = static_sum['经营活动产生的现金流量净额']/static_sum['扣非净利润'] if static_sum['扣非净利润'] else None\n",
    "static_sum['经营现金流/净利润健康度'] = ratio_health_desc(static_sum['经营现金流/净利润'])\n",
    "static_sum['经营现金流/扣非净利润健康度'] = ratio_health_desc(static_sum['经营现金流/扣非净利润'])\n",
    "\n",
    "# 季度滚动TTM，取最近12季度\n",
    "profit_quarter = ak.stock_financial_abstract_ths(symbol=stock_code, indicator=\"按单季度\")\n",
    "profit_quarter = profit_quarter[['报告期', '净利润', '扣非净利润']].copy()\n",
    "profit_quarter[['净利润', '扣非净利润']] = profit_quarter[['净利润', '扣非净利润']].replace('--', None).applymap(parse_amount)\n",
    "profit_quarter = profit_quarter.sort_values(\"报告期\", ascending=False).head(12).reset_index(drop=True)\n",
    "\n",
    "cashflow_quarter = ak.stock_financial_cash_ths(symbol=stock_code, indicator=\"按单季度\")\n",
    "cashflow_quarter = cashflow_quarter[['报告期', '经营活动产生的现金流量净额']].copy()\n",
    "cashflow_quarter['经营活动产生的现金流量净额'] = cashflow_quarter['经营活动产生的现金流量净额'].replace('--', None).apply(parse_amount)\n",
    "cashflow_quarter = cashflow_quarter.sort_values(\"报告期\", ascending=False).head(12).reset_index(drop=True)\n",
    "\n",
    "df_quarter = pd.merge(profit_quarter, cashflow_quarter, on=\"报告期\")\n",
    "\n",
    "# TTM合计\n",
    "net_profit_ttm = df_quarter['净利润'].sum()\n",
    "nonrecurring_net_profit_ttm = df_quarter['扣非净利润'].sum()\n",
    "cashflow_ttm = df_quarter['经营活动产生的现金流量净额'].sum()\n",
    "health_ttm = health_level(cashflow_ttm, net_profit_ttm)\n",
    "ratio_cashflow_netprofit = cashflow_ttm / net_profit_ttm if net_profit_ttm else None\n",
    "ratio_cashflow_nonrecurring = cashflow_ttm / nonrecurring_net_profit_ttm if nonrecurring_net_profit_ttm else None\n",
    "\n",
    "ttm_sum = {\n",
    "    '报告期': '最近12季度TTM合计',\n",
    "    '净利润': net_profit_ttm,\n",
    "    '扣非净利润': nonrecurring_net_profit_ttm,\n",
    "    '经营活动产生的现金流量净额': cashflow_ttm,\n",
    "    '健康度': health_ttm,\n",
    "    '经营现金流/净利润': ratio_cashflow_netprofit,\n",
    "    '经营现金流/扣非净利润': ratio_cashflow_nonrecurring,\n",
    "    '经营现金流/净利润健康度': ratio_health_desc(ratio_cashflow_netprofit),\n",
    "    '经营现金流/扣非净利润健康度': ratio_health_desc(ratio_cashflow_nonrecurring)\n",
    "}\n",
    "\n",
    "# ---------------- 打印 ----------------\n",
    "print(\"=== 最近3年静态数据（按年度） ===\")\n",
    "print(df_annual[['报告期', '净利润', '扣非净利润', '经营活动产生的现金流量净额', '健康度',\n",
    "                 '经营现金流/净利润', '经营现金流/净利润健康度',\n",
    "                 '经营现金流/扣非净利润', '经营现金流/扣非净利润健康度']].applymap(lambda x: format_number(x) if isinstance(x, (int, float)) else x))\n",
    "\n",
    "print(\"\\n=== 最近3年静态数据合计 ===\")\n",
    "print(pd.DataFrame([static_sum]).applymap(lambda x: format_number(x) if isinstance(x, (int, float)) else x))\n",
    "\n",
    "print(\"\\n=== 最近12季度TTM合计 ===\")\n",
    "print(pd.DataFrame([ttm_sum]).applymap(lambda x: format_number(x) if isinstance(x, (int, float)) else x))\n",
    "\n",
    "print(\"\\n说明：经营现金流/净利润 > 1 → 非常健康；0.7 ~ 1 → 基本健康；< 0.5 → 需要警惕\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52c0f5d3",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
